

-- @module : Multiplier
-- @author : ben


library ieee;
use ieee.std_logic_1164.all;

entity Multiplier is 
port (
	clk	: in bit;
	dataIn : in bit_vector(31 downto 0);
	loadM : in bit;
	loadQ : in bit;
	start : in bit;
	reset : in bit;
	dataOutHigh : out bit_vector(31 downto 0);
	dataOutLow : out bit_vector(31 downto 0);
	done : out bit
	);
end Multiplier;     
           

architecture structural of Multiplier is
        
            
component ShiftRegister32 port (clk, clr, load, hold, serialIn : in bit;
	inVec : in bit_vector(31 downto 0);
	outVec : out bit_vector(31 downto 0)
		);
end component;
	
component alu port (
	A, B : in bit_vector(31 downto 0);
	add_notSub : in bit;
	Sum : out bit_vector(31 downto 0)
	);
end component; 

component Controller port (
    clk	: in bit;
    loadM : in bit;
    loadQ : in bit;
    start : in bit;
    reset : in bit;
    Q_zero : in bit;
    Q_prev : in bit;
    counter_overflow : in bit;
    
    clear : out bit;
    done : out bit;
    M_load : out bit;
    A_load : out bit;
    Q_load : out bit;
    M_hold : out bit;
    A_hold : out bit;
    Q_hold : out bit;
    Q_Prev_hold : out bit;
    add_notSub : out bit;
    counter_en : out bit
    );
end component;

component Counter5 port (
		clk : in bit;
		hold_al : in bit; -- active low
		clr_al : in bit;
		overFlow : out bit;
		count : out bit_vector(4 downto 0)
	);
end component; 

component dFlipFlopWithHold port (
    	d : in bit;
    	clk : in bit;
    	clr_al : in bit;
    	hold : in bit;
    	q, qn : out bit
	);
end component;

for all : ShiftRegister32 use entity work.ShiftRegister32(RTL);
for all : alu use entity work.alu;
for all : controller use entity work.Controller;
for all : Counter5 use entity work.Counter5;
for all : dFlipFlopWithHold use entity work.dFlipFlopWithHold;

-- master clear signal
signal master_clr : bit;

-- register signals
signal load_m, hold_m : bit;
signal m_out : bit_vector(31 downto 0);
signal load_a, hold_a : bit;
signal a_out : bit_vector(31 downto 0);
signal load_q, hold_q : bit;
signal q_out : bit_vector(31 downto 0);
signal q_last_hold : bit;
signal q_last_out : bit;

-- alu signals
signal alu_out : bit_vector(31 downto 0);
signal add_notSub : bit;

-- counter signals
signal cntr_hold_al : bit;
signal cntr_overflow : bit;
               
begin  

M_REG : ShiftRegister32 port map (clk, master_clr, load_m, hold_m, '0', dataIn, m_out);
A_REG : ShiftRegister32 port map (clk, master_clr, load_a, hold_a, a_out(31), alu_out, a_out);
-- might need a ff (delay) on a_out(0) here!
Q_REG : ShiftRegister32 port map (clk, master_clr, load_q, hold_q, a_out(0), dataIn, q_out);
Q_LAST : dFlipFlopWithHold port map(q_out(0), clk, master_clr, q_last_hold, q_last_out);

dataOutHigh <= a_out;
dataOutLow <= q_out;

ALU1 : alu port map (a_out, m_out, add_notSub, alu_out);

COUNTER1 : Counter5 port map(clk, cntr_hold_al, master_clr, cntr_overflow); 

CONTROLLER1 : controller port map (

	clk,
	loadM,
	loadQ,
	start,
	reset,
	q_out(0),
	q_last_out,
	--q_out(1),
	--q_out(0),
	cntr_overflow,
	
	master_clr,
	done,
	load_m,
	load_a,
	load_q,
	hold_m,
	hold_a,
	hold_q,
	q_last_hold,
	add_notSub,
	cntr_hold_al
	
);

end structural;
